package com.onlyxiahui.common.action.description.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 
 * Description 获取对象 getter setter 属性<br>
 * Date 2020-01-08 15:58:01<br>
 * 
 * @author XiaHui [onlovexiahui@qq.com]<br>
 * @since 1.0.0
 */
public class ActionBeanPropertyBox {

	private Map<Class<?>, Map<Class<?>, List<PropertyDescriptor>>> listMap = new ConcurrentHashMap<>();

	public List<PropertyDescriptor> getPropertyList(Class<?> classType) {
		List<PropertyDescriptor> propertyList = getPropertyList(classType, Object.class);
		return propertyList;
	}

	public List<PropertyDescriptor> getPropertyList(Class<?> classType, Class<?> stopClass) {
		List<PropertyDescriptor> propertyList = new ArrayList<>();
		if (null != classType && ActionClassUtil.isBean(classType) && !isObjectClass(classType)) {
			try {
				Map<Class<?>, List<PropertyDescriptor>> map = listMap.get(classType);
				if (null == map) {
					map = new ConcurrentHashMap<>(256);
					listMap.put(classType, map);
				}

				if (null == stopClass) {
					stopClass = Object.class;
				}

				List<PropertyDescriptor> list = map.get(stopClass);
				if (null == list) {
					list = new ArrayList<>();
					BeanInfo bi = Introspector.getBeanInfo(classType, stopClass);
					PropertyDescriptor[] pds = bi.getPropertyDescriptors();
					for (PropertyDescriptor pd : pds) {
						list.add(pd);
					}
					map.put(stopClass, list);
				}
				for (PropertyDescriptor pd : list) {
					propertyList.add(pd);
				}
			} catch (IntrospectionException e) {
				e.printStackTrace();
			}
		}
		return propertyList;
	}

	public List<PropertyDescriptor> getReadPropertyList(Class<?> classType) {
		return getReadPropertyList(classType, Object.class);
	}

	public List<PropertyDescriptor> getReadPropertyList(Class<?> classType, Class<?> stopClass) {
		List<PropertyDescriptor> propertyList = new ArrayList<>();
		List<PropertyDescriptor> list = getPropertyList(classType, stopClass);
		for (PropertyDescriptor pd : list) {
			if (null != pd.getReadMethod()) {
				propertyList.add(pd);
			}
		}
		return propertyList;
	}

	public List<PropertyDescriptor> getWritePropertyList(Class<?> classType) {
		return getWritePropertyList(classType, Object.class);
	}

	public List<PropertyDescriptor> getWritePropertyList(Class<?> classType, Class<?> stopClass) {
		List<PropertyDescriptor> propertyList = new ArrayList<>();
		List<PropertyDescriptor> list = getPropertyList(classType, stopClass);
		for (PropertyDescriptor pd : list) {
			if (null != pd.getWriteMethod()) {
				propertyList.add(pd);
			}
		}
		return propertyList;
	}

	public Map<String, PropertyDescriptor> getReadPropertyMap(Class<?> classType) {
		Map<String, PropertyDescriptor> dataMap = new HashMap<>(100);
		List<PropertyDescriptor> list = getReadPropertyList(classType);
		for (PropertyDescriptor pd : list) {
			if (null != pd.getReadMethod()) {
				dataMap.put(pd.getName(), pd);
			}
		}
		return dataMap;
	}

	public Map<String, PropertyDescriptor> getWritePropertyMap(Class<?> classType) {
		Map<String, PropertyDescriptor> dataMap = new HashMap<>(100);
		List<PropertyDescriptor> list = getWritePropertyList(classType);
		for (PropertyDescriptor pd : list) {
			if (null != pd.getReadMethod()) {
				dataMap.put(pd.getName(), pd);
			}
		}
		return dataMap;
	}

	public Map<String, PropertyDescriptor> getPropertyMap(Class<?> classType) {
		Map<String, PropertyDescriptor> dataMap = new HashMap<>(100);
		List<PropertyDescriptor> list = getPropertyList(classType);
		for (PropertyDescriptor pd : list) {
			if (null != pd.getReadMethod()) {
				dataMap.put(pd.getName(), pd);
			}
		}
		return dataMap;
	}

	public static boolean isObjectClass(Class<?> classType) {
		return null != classType && classType.equals(Object.class);
	}
}
